﻿//==============================================================================
// Random 
//------------------------------------------------------------------------------
///**
//  @file       Random.h
//  @brief      Random
//  @author     Riki
//*/
//==============================================================================

#pragma once

#include "Common.h"

namespace LNote
{
namespace Core
{
namespace Math
{

//==============================================================================
// Random
//------------------------------------------------------------------------------
///**
//  @brief      乱数のクラス
//  @par
//              アルゴリズムは Xorshift です。<br>
//				Copyright 2003 George Marsaglia.
//*/
//==============================================================================
class Random : public Base::ReferenceObject
{
public:
	LN_TYPE_INFO_ACCESS_DECL;

public:

	//----------------------------------------------------------------------
	///**
	//	@brief      デフォルトの乱数シードの設定
	//
	//  @par
	//              デフォルトコンストラクタを使った場合に、
	//              初期状態で設定される乱数シード値を設定します。<br>
	//              <br>
	//              初期値は 0 です。
	//*/
	//----------------------------------------------------------------------
    static void setDefaultSeed( int seed_ );

	//----------------------------------------------------------------------
	///**
	//	@brief      デフォルトの乱数シードの取得
	//*/
	//----------------------------------------------------------------------
    static int getDefaultSeed();

	//----------------------------------------------------------------------
	///**
	//	@brief      シード値から一定の値を取得する
	//*/
	//----------------------------------------------------------------------
    static int getIntHash( int seed_ );

	//----------------------------------------------------------------------
	///**
	//	@brief      シード値から一定の値を取得する
	//*/
	//----------------------------------------------------------------------
    static float getFloatHash( int seed_ );

	//----------------------------------------------------------------------
	///**
	//	@brief      シード値から一定の値を取得する ( _a <= x < b_ )
	//*/
	//----------------------------------------------------------------------
    static float getFloatHash( int seed_, float a_, float b_ );

	//----------------------------------------------------------------------
	///**
	//	@brief      シード値から一定の値を取得する
	//*/
	//----------------------------------------------------------------------
    static float getFloatHashEx( int seed_, ExRandType rand_type_, float v0_, float v1_ );

public:

	//----------------------------------------------------------------------
	///**
	//	@brief      デフォルトコンストラクタ
	//
	//  @par
	//              setDefaultSeed() で設定されている値を乱数シードとします。<br>
	//              <br>
	//              初期値は 0 です。
	//*/
	//----------------------------------------------------------------------
	Random();

	//----------------------------------------------------------------------
	///**
	//	@brief      コンストラクタ (乱数シード値を指定)
	//*/
	//----------------------------------------------------------------------
	Random( int seed_ );

public:

	//----------------------------------------------------------------------
	///**
	//	@brief      乱数シードの設定
	//*/
	//----------------------------------------------------------------------
    void setSeed( int seed_ );

	//----------------------------------------------------------------------
	///**
	//	@brief      整数値乱数の取得
	//*/
	//----------------------------------------------------------------------
    int getInt();

	//----------------------------------------------------------------------
	///**
	//	@brief      整数値乱数の取得 ( 0 <= x < a_ )
	//*/
	//----------------------------------------------------------------------
    int getInt( int a_ );

	//----------------------------------------------------------------------
	///**
	//	@brief      整数値乱数の取得 ( _a <= x < b_ )
	//*/
	//----------------------------------------------------------------------
    int getInt( int a_, int b_ );

	//----------------------------------------------------------------------
	///**
	//	@brief      実数値乱数の取得
	//*/
	//----------------------------------------------------------------------
    float getFloat();

	//----------------------------------------------------------------------
	///**
	//	@brief      実数値乱数の取得 ( 0 <= x < a_ )
	//*/
	//----------------------------------------------------------------------
    float getFloat( float a_ );

	//----------------------------------------------------------------------
	///**
	//	@brief      実数値乱数の取得 ( _a <= x < b_ )
	//*/
	//----------------------------------------------------------------------
    float getFloat( float a_, float b_ );


	/// 整数値乱数の取得 (中央値 - ±幅/2  10, 10 だと 5～15)
	int getIntRange(int center_, int range_) { return center_ - range_ / 2 + getInt(range_ + 1); }

	/// 実数値乱数の取得 (中央値 - ±幅/2  10, 10 だと 5～15)
    float getFloatRange( float center_, float range_ ) { return center_ - range_ / 2 + getFloat( range_ ); }


	//----------------------------------------------------------------------
	///**
	//	@brief      実数値乱数の取得
	//
	//  @param[in]  v0_        : 入力値 (値の意味は rand_type_ によって変わる)
	//  @param[in]  v1_        : 入力値
	//  @param[in]  rand_type_ : v0_ と v1_ の意味を表す値
	//  @param[in]  rate_      : 処理に使うレート値 (補間値 0.0～1.0。通常、これをランダム値にする)
	//  @param[in]  rate_type_ : rate_ の意味を表す値
	//
	//  @par
	//              まず最初に、v0_、v1_、rand_type_ からランダム値の範囲を調べます。
	//              LN_RAND_MINMAX が指定されている場合、最小値は v0_、最大値は v1_ が
	//              そのまま使用されます。<br>
	//              <br>
	//              次に、rate_type_ によって処理を行います。<br>
	//              <br>
	//              LN_RANDRATE_MIN、LN_RANDRATE_MAX の場合は、最小値と最大値を
	//              rate_ の値で単純に線形補完した値を返します。
	//              引数の値がすべて同じ場合は常に同じ値を返します。<br>
	//              <br>
	//              LN_RANDRATE_CENTER、LN_RANDRATE_OUTER の場合は、
	//              中央値を求めた後に最小値、最大値のどちらを使って計算するかを
	//              乱数を使って決めます。(2択)<br>
	//              その後、決めた値と中央値を rate_ によって線形補間した値を返します。
	//
	//  @note
	//              いまのところ、エフェクトやパーティクルのランダムな動きに
	//              特定の規則性を持たせるユーティリティみたいな感じで使ってる。
	//*/
	//----------------------------------------------------------------------
    float getFloatEx( float v0_, float v1_, ExRandType rand_type_, float rate_, ExRandRateType rate_type_ );

private:

	lnU32 x, y, z, w;
};

} // namespace Math
} // namespace Core
} // namespace LNote

//==============================================================================
//
//==============================================================================